/*
 * Copyright 2011 Mark Davidson.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.dctmcommons.impl.methods;

import java.util.ArrayList;
import java.util.List;

import com.documentum.bpm.rtutil.WorkflowMethod;
import com.documentum.fc.client.IDfActivity;
import com.documentum.fc.client.IDfCollection;
import com.documentum.fc.client.IDfModule;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.client.IDfWorkitem;
import com.documentum.fc.common.DfException;
import com.documentum.fc.common.DfId;
import com.documentum.fc.common.DfList;
import com.documentum.fc.common.DfLogger;
import com.documentum.fc.common.IDfList;

/**
 * Base class for workflow methods. Hot deployable.
 */
public abstract class AbstractWorkflowMethod
	extends WorkflowMethod implements IDfModule {

	public static final int STATUS_SUCCESS = 0;
	public static final int STATUS_FAILURE = 1;

	public static final boolean WORKITEM_SUCCESS = true;
	public static final boolean WORKITEM_FAILURE = false;

	private static final String ATTR_COMPONENT_ID = "r_component_id";

	/**
	 * Specifies the next activity to be the default forward activity.
	 * @throws DfException The repository exception
	 */
	public void setDefaultForwardActivityAsNextActivity(
													final IDfWorkitem workitem)
		throws DfException {
		setNextActivity(workitem, 0, true);
	}

	/**
	 * Specifies the next activity to be the default reject activity.
	 * @throws DfException The repository exception
	 */
	public void setDefaultRejectActivityAsNextActivity(
													final IDfWorkitem workitem)
		throws DfException {
		setNextActivity(workitem, 0, false);
	}

	/**
	 * Sets the next activity.
	 * @param workitem The workitem
	 * @param activityNumber The activity number
	 * @param isForwardActivity Whether to use a forward activity (otherwise use
	 * a reject activity)
	 * @throws DfException The repository exception
	 */
	public void setNextActivity(final IDfWorkitem workitem,
								final int activityNumber,
								final boolean isForwardActivity)
		throws DfException {
		final IDfList activities = isForwardActivity ?
						workitem.getForwardActivities() :
						workitem.getRejectActivities();
		final IDfActivity activity = (IDfActivity) activities
														.get(activityNumber);
		final IDfList nextActivities = new DfList();
		nextActivities.append(activity);
		workitem.setOutputByActivities(nextActivities);
	}

	/**
	 * Gets the default package document from the workitem.
	 * @return The document
	 * @throws DfException The repository exception
	 */
	public IDfSysObject getDefaultPackageDocumentFromWorkitem(
													final IDfWorkitem workitem)
		throws DfException {
		
		final IDfSession session = workitem.getSession();
		final String[][] packageDocIds = getPackageDocIds(workitem);
		
		if (packageDocIds == null) {
			return null;
		} else {
			final String docId = packageDocIds[0][0];
			return (IDfSysObject) session.getObject(new DfId(docId));
		}
	}
	
	/**
	 * Gets a list of documents for the associated packages.
	 * @throws DfException The repository exception
	 */
	public String[][] getPackageDocIds(final IDfWorkitem workitem)
		throws DfException {
		final List<String[]> packageDocIds = new ArrayList<String[]>();
		
		if (workitem != null) {
			final IDfCollection packages = workitem.getPackages("");
			
			if (packages != null) {
				try {
					while (packages.next()) {
						final int numDocs = packages
											.getValueCount(ATTR_COMPONENT_ID);
						if (numDocs > 0) {
							final String[] docIds = new String[numDocs];
							for (int i = 0; i < numDocs; i++) {
								final String docId = packages
											.getRepeatingId(ATTR_COMPONENT_ID,
															i)
												.getId();
								docIds[i] = docId;
							}
							packageDocIds.add(docIds);
						}
					}
				} catch (DfException e) {
					DfLogger.error(
								this,
								"Failed to iterate workflow package documents",
								null,
								e);
					throw e;
				} finally {
					packages.close();
				}
			}
		}
		
		if (packageDocIds.size() == 0) {
			return null;
		} else {
			return packageDocIds.toArray(new String[][] {});
		}
	}
}

